Gargoyle crash bugs

The "crash" feature of the gargoyle when it dies in Heretic, whereby it enters a special falling state until it hits the ground and then explodes into gibs on contact, is subject to several bugs which can cause interesting behaviors.

Mechanics
The was added to the  structure by Raven Software to allow the gargoyle's special falling behavior. Special-case code in the function will place it into this state when it is detected as having hit the ground. The normal death frame of a gargoyle always depicts it in a pose of falling through the air. It is the which transforms it into a pile of gibs and spawns additional gib objects.

No gibs
If the gargoyle is already touching the ground before the game makes the first check for impact, but after the gargoyle has already entered its, then the crash will never occur as the function will never be invoked for the object at all. This will cause the gargoyle to remain solid and affected by gravity while holding its falling pose. This most commonly occurs if the gargoyle is perfectly level with a floor behind it and is pushed back onto the floor by the damage that kills it, resulting in no Z momentum. A common place to observe this is in, just beyond the yellow key door.

Multiple gibs
If the gargoyle crosses multiple sectors while dying, such as by sliding down a set of stairs, it may enter its repeatedly, becoming a fountain of gibs in the process. This happens due to interaction between the functions and ; neither function checks if a gargoyle is already in its, so when it hits each floor, it satisfies the conditions for the crash animation to occur.

Floating dead gargoyle
If the gargoyle suffers an "extreme" death (gibbing by normal standards), it enters a different frame (the ) the same way as other monsters, but still utilizes the same crash logic. However, Raven wanted the gargoyle to appear to fly much further away from the player when this occurs, to reflect the power of the attack that killed it, so they temporarily assign the gargoyle the bit flag to cause it to temporarily float in the air. This flag is assigned by the action function and removed several frames later in the  action function, via the following state sequence: {SPR_IMPX, 18, 5, A_ImpXDeath1, S_IMP_XDIE2, 0, 0}, // S_IMP_XDIE1 {SPR_IMPX, 19, 5, NULL, S_IMP_XDIE3, 0, 0}, // S_IMP_XDIE2 {SPR_IMPX, 20, 5, NULL, S_IMP_XDIE4, 0, 0}, // S_IMP_XDIE3 {SPR_IMPX, 21, 5, A_ImpXDeath2, S_IMP_XDIE5, 0, 0}, // S_IMP_XDIE4 {SPR_IMPX, 22, 5, NULL, S_IMP_XDIE5, 0, 0}, // S_IMP_XDIE5 When is invoked, it will check if the monster has touched the floor, and if so, it will then set it into its. There is a logical error in this setup, however: it is possible for the logic in to set the gargoyle to its  as usual between these two frames, and when this occurs, the  frame is never entered by the monster at all. This results in the gibbed gargoyle keeping the no-gravity bit flag - it will remain floating in the air forever. This occurs if the gargoyle dies in the air but crosses a raised ledge at its exact height during the 15 tics between the two action function calls. This means that gibbing a gargoyle near a window frame is the easiest way to cause it.

Fixes
These bugs are fixed by some Heretic source ports:
 * Eternity Engine
 * ZDoom and derivatives (GZDoom et al.)

The problem of no gibbing is addressed by adding a special-case check for objects with crash animations already being in contact with a floor when they die; they will be set into that state immediately instead of assuming that they will necessarily acquire Z momentum at some later point in execution.

The problem of gibbing multiple times must be addressed by adding some type of tracking to the actor. In both Eternity and ZDoom this is accomplished with an internal bit flag which records the "has crashed" state for that object. An object attempting to crash again will not repeat the animation if this bit is set.

The problem of a floating gibbed gargoyle is fixed simply by always removing the no-gravity bit flag in the routine as well, so that it will be removed regardless of how a gargoyle enters the crash animation.